from datetime import datetime
from typing import List, Optional, Literal
from pydantic import BaseModel, Field, ConfigDict, field_validator
from enum import Enum


# ===== 嵌套结构模型 =====
class GeoPoint(BaseModel):
    lat: float = Field(..., description="纬度坐标")
    lng: float = Field(..., description="经度坐标")


class City(BaseModel):
    id: int = Field(..., description="城市ID")
    name: str = Field(..., description="城市名称")
    level: Optional[str] = Field(None, description="行政级别")


class Province(BaseModel):
    id: int = Field(..., description="省份ID")
    name: str = Field(..., description="省份名称")
    level: Optional[str] = Field(None, description="行政级别")


class District(BaseModel):
    id: int = Field(..., description="区域ID")
    name: str = Field(..., description="区域名称")
    level: Optional[str] = Field(None, description="行政级别")


class ClockRuleTime(BaseModel):
    after_time: Optional[int] = Field(None, alias="afterTime", description="迟到允许时间（分钟）")
    before_time: Optional[int] = Field(None, alias="beforeTime", description="早退允许时间（分钟）")
    clock_in_time: Optional[str] = Field(None, alias="clockInTime", description="打卡时间范围")
    index: Optional[int] = Field(None, description="时间规则索引")
    next_day: Optional[bool] = Field(None, alias="nextDay", description="是否跨天")


class ClockRule(BaseModel):
    id: int = Field(..., description="打卡规则ID")
    area: Optional[str] = Field(None, description="适用区域")
    area_name: Optional[str] = Field(None, alias="areaName", description="区域名称")
    rule_name: Optional[str] = Field(None, alias="ruleName", description="规则显示名")
    rule_time: Optional[List[ClockRuleTime]] = Field(None, alias="ruleTime", description="时间规则")
    selected: Optional[bool] = Field(None, description="是否选中")


class ClockInRecord(BaseModel):
    punch_in_time: Optional[datetime] = Field(None, alias="punchInTime", description="打卡时间戳")
    type: Optional[int] = Field(None, description="打卡类型（0:上班 1:下班）")


class FencePoint(BaseModel):
    latitude: float = Field(..., description="围栏点纬度")
    longitude: float = Field(..., description="围栏点经度")


class ElectronicFence(BaseModel):
    id: int = Field(..., description="电子围栏ID")
    name: str = Field(..., description="围栏名称")
    center_lat: Optional[float] = Field(None, alias="centerLat", description="中心点纬度")
    center_lon: Optional[float] = Field(None, alias="centerLon", description="中心点经度")
    depart_id: Optional[int] = Field(None, alias="departId", description="所属部门ID")
    points: Optional[List[FencePoint]] = Field(..., description="围栏边界点集合")
    radius: Optional[int] = Field(None, description="圆形围栏半径（米）")
    type: int = Field(..., description="围栏类型（1:圆形 2:多边形）")


class OffMessageUser(BaseModel):
    user_id: int = Field(..., alias="userId", description="用户ID")
    nick_name: str = Field(..., alias="nickName", description="昵称")
    user_name: str = Field(..., alias="userName", description="用户名")
    personal_phone: str = Field(..., alias="personalPhone", description="手机号")
    open_id: Optional[str] = Field(None, alias="openId", description="微信OpenID")
    checked: bool = Field(..., description="是否选中")


class WorkArea(BaseModel):
    id: int = Field(..., description="工作区域ID")
    name: str = Field(..., description="工作区域名称")


class DataAuthority(BaseModel):
    depart: List[int | None] = Field(..., description="数据权限部门ID")


class HealthProportion(BaseModel):
    activation: Optional[float] = Field(None, description="设备激活比例")
    duration: Optional[float] = Field(None, description="工作时长比例")


# ===== 主数据模型 =====
class ElectronicCardModel(BaseModel):
    model_config = ConfigDict(
        populate_by_name=True,  # 支持别名映射
        arbitrary_types_allowed=True,
        json_encoders={datetime: lambda v: v.strftime("%Y-%m-%dT%H:%M:%S.%fZ")}
    )

    # 核心标识字段
    es_id:Optional[str]= Field(None)
    es_index:Optional[str]= Field(None)
    id: int = Field(..., description="主键ID", alias="_id")
    user_id: Optional[int] = Field(None, alias="userId")
    dev_id: Optional[int] = Field(None, alias="devId")
    imei: str = Field(..., description="设备IMEI码", max_length=15)
    dataAuthority: Optional[DataAuthority] = Field(None, description="数据权限")

    # 时间相关字段
    create_date: datetime = Field(default_factory=datetime.utcnow, alias="createDate", description="创建时间")
    at: datetime = Field(default_factory=datetime.utcnow)
    gtm: Optional[datetime] = Field(None, description="GPS时间戳")
    ctm: Optional[datetime] = Field(None, description="设备当前时间")
    #
    # # 人员信息
    name: Optional[str] = Field(..., description="用户姓名", max_length=50)
    nick_name: Optional[str] = Field(None, alias="nickName", description="用户昵称")
    sex: Optional[str] = Field(None, description="性别")
    age: Optional[int] = Field(None,  description="年龄")
    head_img: Optional[str] = Field(None, alias="headImg", description="头像URL")
    personal_phone: Optional[str] = Field(None, alias="personalPhone", description="手机号码")
    #
    # # 组织架构
    depart: int = Field(None, description="所属部门ID")
    depart_name: str = Field(None, alias="departName", description="部门名称")
    attendance_group_id: int = Field(None, alias="attendanceGroupId", description="考勤组ID")
    attendance_group_name: str = Field(None, alias="attendanceGroupName", description="考勤组名称")
    job_duty_id: Optional[int] = Field(None, alias="jobDutyId")
    job_post: Optional[str] = Field(None, alias="jobPost")
    job_duty_name: Optional[str] = Field(None, alias="jobDutyName", description="职务名称")
    project_id: int = Field(None, alias="projectId", description="项目ID")

    # 地理位置
    city: Optional[City] = Field(None, description="城市信息")
    province: Optional[Province] = Field(None, description="省份信息")
    district: Optional[District] = Field(None, description="行政区信息")
    lat: float = Field(None, description="纬度")
    lon: float = Field(None, description="经度")

    # 考勤规则
    # clock_rule_id: int = Field(..., alias="clockRuleId", description="打卡规则ID")
    clock_rule: List[ClockRule] = Field(None, alias="clockRule", description="打卡规则详情")
    # fence_id: int = Field(..., alias="fenceId", description="电子围栏ID")
    fence: Optional[List[ElectronicFence]] = Field(None, description="电子围栏详情")
    #
    # # 设备状态
    device_type: int = Field(None, alias="deviceType", description="设备类型")
    wearing: Optional[bool] = Field(None, description="佩戴状态")
    on_line: Optional[bool] = Field(None, alias="onLine", description="在线状态")
    battery: Optional[int] = Field(0, description="电池电量百分比")

    # 健康监测
    heart_rate: Optional[int] = Field(None, alias="heartRate",  description="心率")
    blood_oxygen: Optional[int] = Field(None, alias="bloodOxygen", description="血氧饱和度")
    body_temperature: Optional[float] = Field(None, alias="bodyTemperature", description="体温")
    blood_pressure_high: Optional[int] = Field(None, alias="bloodPressureHigh", description="收缩压")
    blood_pressure_low: Optional[int] = Field(None, alias="bloodPressureLow", description="舒张压")

    # 辅助字段
    # automatic_clock_in: bool = Field(..., alias="automaticClockIn", description="自动打卡开关")
    # state: int = Field(..., description="设备状态码")
    region: Optional[str] = Field(None, description="地理区域")
    work_area_name: str = Field(None, alias="workAreaName", description="工作区域名称")
    # proportion: Optional[HealthProportion] = Field(None, description="健康指标比例")
    off_message_users: Optional[List[OffMessageUser]] = Field(None, alias="offMessageUsers", description="离线通知接收人")

    # ===== ES 集成方法 =====
    def to_es_document(self) -> dict:
        """转换为ES文档格式，处理嵌套结构和特殊字段"""
        doc = self.model_dump(by_alias=True, exclude_none=True)

        # 处理地理坐标点
        doc["location"] = {
            "lat": self.lat,
            "lon": self.lng
        }

        # 添加时间戳字段
        doc["@timestamp"] = datetime.utcnow().isoformat()

        return doc